use ho_string::HoString;
use ncurses::*;
use crate::data::ContentChar;

pub struct SubWinParam {
    pub screen: WINDOW,
    pub width: i32,
    pub height: i32,
    pub x: i32,
    pub y: i32
}

pub struct Window {
    pub color_id: i16,
    pub color_fg: i16,
    pub color_bg: i16,
    pub title_str: String,
    pub width: i32,
    pub height: i32,
    pub win: WINDOW,
    pub content: String
}

impl SubWinParam {
    pub fn new(screen: WINDOW, width: i32, height: i32, x: i32, y: i32) -> Self {
        return Self { screen, width, height, x, y };
    }
}

impl Window {
    pub fn new(id: i16, fg: i16, bg: i16, string: String, w: i32, h: i32, sub_win_param: SubWinParam) -> Self {
        return Self {
            color_id: id,
            color_fg: fg,
            color_bg: bg,
            title_str: string,
            width: w,
            height: h,
            win: subwin(
                sub_win_param.screen,
                sub_win_param.height,
                sub_win_param.width,
                sub_win_param.y,
                sub_win_param.x
            ),
            content: String::new()
        };
    }
}

pub fn init_window(file_explorer_width: f64) -> Vec<Window> {
    let mut ui: Vec<Window> = Vec::new();
    let explorer_width: i32 = (COLS() as f64 * file_explorer_width).floor() as i32;
    let file_explorer: Window = Window::new(
        0,
        COLOR_WHITE,
        COLOR_BLACK,
        String::from("File Explorer"),
        explorer_width,
        LINES() - 1,
        SubWinParam::new(
            stdscr(),
            explorer_width,
            LINES() - 1,
            0,
            0
        )
    );
    let editor: Window = Window::new(
        1,
        COLOR_WHITE,
        COLOR_BLACK,
        String::from("Editor"),
        COLS() - explorer_width,
        LINES() - 1,
        SubWinParam::new(
            stdscr(),
            COLS() - explorer_width,
            LINES() - 1,
            explorer_width,
            0
        )
    );
    ui.push(file_explorer);
    ui.push(editor);
    return ui;
}

pub fn add_content(ui: &Vec<Window>, content: &HoString) -> Vec<Vec<ContentChar>> {
    let mut c_str: String = content.to_string();
    let mut cursor_y: usize = 1;
    let mut cursor_x: usize = 1;
    let editor: &Window = ui.get(1).unwrap();
    let mut content_chars: Vec<Vec<ContentChar>> = Vec::new();
    let mut chars: Vec<ContentChar> = Vec::new();
    c_str.push_str("\0");
    for c in c_str.chars() {
        if c == '\0' {
            chars.push(ContentChar::new(c, cursor_y, cursor_x));
            content_chars.push(chars);
            return content_chars;
        }
        mvwaddch((*editor).win, cursor_y as i32, cursor_x as i32, c as chtype);
        chars.push(ContentChar::new(c, cursor_y, cursor_x));
        if c == '\n' {
            cursor_x = 1;
            cursor_y += 1;
            if cursor_y as i32 >= (*editor).height - 2 {
                if chars.len() > 0 {
                    content_chars.push(chars);
                }
                return content_chars;
            }
            content_chars.push(chars.clone());
            chars.clear();
        } else {
            if cursor_x as i32 >= (*editor).width - 2 {
                cursor_x = 1;
                cursor_y += 1;
                if cursor_y as i32 >= (*editor).height - 2 {
                    if chars.len() > 0 {
                        content_chars.push(chars);
                    }
                    return content_chars;
                }
            } else {
                cursor_x += 1;
            }
        }
    }
    if chars.len() > 0 {
        content_chars.push(chars);
    }
    return content_chars;
}

pub fn draw_border(ui: &Vec<Window>) {
    for value in ui {
        wborder(
            (*value).win,
            '|' as chtype,
            '|' as chtype,
            '-' as chtype,
            '-' as chtype,
            '+' as chtype,
            '+' as chtype,
            '+' as chtype,
            '+' as chtype
        );
        mvwaddstr((*value).win, 0, 0, (*value).title_str.as_str());
        wrefresh((*value).win);
    }
}
